#include "ResPonseThread.h"
#include "SocketThread.h"
#include "MessageManager.h"
//;
//#include "CCLuaEngine.h"
#include "GameNet.h"
#include "MessageHandleManager.h"
using namespace chrono;
using namespace this_thread;

ResPonseThread* ResPonseThread::m_pInstance = NULL;
void* ResPonseThread::buf = NULL;
ResPonseThread* ResPonseThread::getInstance(){
	if (!m_pInstance) {
		m_pInstance = new ResPonseThread();
		m_pInstance->onReconned = nullptr;
		m_pInstance->retain();
	}
	return m_pInstance;
}
ResPonseThread::ResPonseThread(void){
	buf = malloc(BUFF_SIZE);
	this->m_msglistener = NULL;

	started = detached = false;

	addmsgListenerEvent(callFunc_selectormsg(ResPonseThread::msgCallBack), this);
	addnotconListenerEvent(callFunc_selectormsg(ResPonseThread::notContCallBack), this);
	notfication = __NotificationCenter::sharedNotificationCenter();
	Director::getInstance()->getScheduler()->scheduleSelector(schedule_selector(ResPonseThread::schedule_func), this, 0.1, false);
}


ResPonseThread::~ResPonseThread(void){
	free(buf);
	stop();
}
int ResPonseThread::start(void * param){
	int errCode = 0;
	do{
		started = true;
		handle = thread(threadFunc, this);
	} while (0);
	return errCode;
}
//计时器。如果有消息。投入到脚本
void ResPonseThread::schedule_func(float ti){
	if (!m_pInstance->messages.empty()){
		_messageQueueMutex.lock();
		Message *m = m_pInstance->messages.front();
		if (!m){
			__String *msgs = __String::create("连接失败,请检查网络！");
			notfication->postNotification("connback", msgs);
		}
		else{
			Director::getInstance()->getScheduler()->performFunctionInCocosThread([m]{
				MessageHandleManager::getInstance()->recv(m);
			});
			/*if (MessageReciver::Reciver != NULL){
			MessageReciver::Reciver->recv(m);
			}*/
			//notfication->postNotification("msgcallback", recivedMsg);
		}
		//notfication->postNotification("callback", msg);
		m_pInstance->messages.pop_front();
		_messageQueueMutex.unlock();
	}
}
//循环试探是否有新的消息 如果有 存入队列
void* ResPonseThread::threadFunc(void *arg){
	ResPonseThread* thred = (ResPonseThread*)arg;
	while (thred->started){
		ODSocket csocket = SocketThread::getInstance()->getSocket();
		if (SocketThread::getInstance()->state == Disconnected){
			(thred->m_msglistener->*(thred->notconselector))(1, NULL);

			sleep_for(milliseconds(1000));

			continue;
		}
		if (csocket.Select() == -2){
			int32 len = 0;
			int num = csocket.Recv((char*)buf, sizeof(len), 0);
			char* buffer = (char*)buf;
			memcpy(&len, buf, sizeof(len));
			len = ntohl(len);
			if (num == -1){//连接断开
				auto lastState = SocketThread::getInstance()->state;
				SocketThread::getInstance()->state = Disconnected;
				if (SocketThread::getInstance()->onConnectionClosed != nullptr && !SocketThread::InBackground){
					log("onConnectionClosed in recive Msg thread");
					if (lastState != Disconnected)
						SocketThread::getInstance()->onConnectionClosed();
				}
				continue;
			}
			else{
				int readCount = 0;
				while (readCount < len){
					readCount += csocket.Recv((char*)buf + readCount, len - readCount, 0);
				}

				//id

				int32 id;
				memcpy(&id, buf, sizeof(id));
				id = ntohl(id);

				//string str = bytestohexstring((char*)buf, len);
				/*//time

				int32 time;
				memcpy(&time, (char*)buf + sizeof(id), sizeof(time));
				time = ntohl(time);
				log("time %d", time);*/
				//data

				thred->recv_buf.writeDatas((char*)buf + sizeof(id), len - sizeof(id));

				Message* msg = MessageManager::getMsg(id);
				if (msg == NULL){
					log("msg is null:(%d)", id);
					continue;
				}
				msg->reset();
				if (!msg->read_from(thred->recv_buf)){
					log("read is wrong");
					continue;
				}
				(thred->m_msglistener->*(thred->msgselector))(msg->getId(), msg);
			}
		}
		sleep_for(milliseconds(100));
		m_pInstance->sleep(100);
	}
	return NULL;
}

string ResPonseThread::bytestohexstring(char* bytes, int bytelength){
	string str("");
	string str2("0123456789abcdef");
	for (auto i = 0; i < bytelength; i++) {
		int b;
		b = 0x0f & (bytes[i] >> 4);
		char s1 = str2.at(b);
		str.append(1, str2.at(b));
		b = 0x0f & bytes[i];
		str.append(1, str2.at(b));
		char s2 = str2.at(b);
	}
	return str;
}

void ResPonseThread::stop(){
	if (started && !detached) {
		handle.detach();
		detached = true;
		log("关闭接受数据线程");
	}
}

void * ResPonseThread::wait(){
	void * status = NULL;
	if (started && !detached) {
		handle.join();
	}
	return status;
}
void ResPonseThread::sleep(int secstr){
	timeval timeout = { secstr / 1000, secstr % 1000 };
	select(0, NULL, NULL, NULL, &timeout);
}

void ResPonseThread::detach(){
	if (started && !detached) {
		handle.detach();
	}
	detached = true;
}
void ResPonseThread::notContCallBack(short commttpe, Message* msg){
}

//有消息的回调
void ResPonseThread::msgCallBack(short commttpe, Message* msg){
	if (msg){
		//log("消息id %d", msg->getId());
	}
	if (commttpe) {
		_messageQueueMutex.lock();
		messages.push_back(msg);
		_messageQueueMutex.unlock();
	}
}
//没有消息的回调

//void ResPonseThread::notContCallBack(short commttpe, Message* msg){
//}
//void ResPonseThread::notContCallBack(short commttpe, Message* msg){}


//log("noconnetction");
/*if (!GameNet::reconn(SocketThread::getInstance()->ip, SocketThread::getInstance()->port)){
num++;
}
else{
num = 0;
SocketThread::getInstance()->state = Connected;
if (onReconned != nullptr)
onReconned();
}
if (this->num >= 5){
//调用脚本通知重新连接5次失败.检查网络
if (commttpe) {
_messageQueueMutex.lock();
messages.push_back(msg);
_messageQueueMutex.unlock();

}

}*/


